package com.example.onlinemonitoring.comCenter;

import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Gbjfsensor;
import com.example.onlinemonitoring.model.Gbjfhistory;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.serviceImpl.GbjfsensorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Scope;
import java.text.ParseException;
import java.util.Date;

/**
 * 干变局放
 */
/*
 * 这里beanName需要和数据库Appdevice中的simple对应并加上Com,不对应请自行修改
 * 例:simple:dlhl
 * 
 * @Service("dlhlCom")
 */
@Service("gbjfCom")
@Scope("prototype")
public class GbjfCom extends CommPortManager {
    @Autowired
    private GbjfsensorServiceImpl gbjfsensorServiceImpl;

    @Override
    public void receiveData(String str) {
        try {
            str = str.toUpperCase();
            setText(str);
            // 01033C 6
            // 4231500200260021 16
            // 0002 4
            // 0060 电量 4
            // FFBA 幅值 4
            // FFF6FFF6FFF6FFF60000FE700005FE70 32
            // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
            // 01033C423150020026002100020060FFBAFFF6FFF6FFF6FFF60000FE700005FE70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4DC
            // 获取功能码
            if (!str.substring(2, 4).equals("03"))
                return;
            // 获取地址
            int addr = parseHex4(str.substring(0, 2));
            // String content = str.substring(6, 14);
            reSend[addr] = 0;
            addrindex++;
            setText("设备返回数据： 站点号：" + ad.getStationid() + " 设备组：" + ad.getDevicegroup() + " 设备地址：" + addr);
            // 默认最大两个传感器
            for (int i = 1; i <= ad.getPointcount(); i++) {
                Gbjfsensor gbjf = new Gbjfsensor();
                gbjf.setStationid(ad.getStationid());
                gbjf.setDevicegroup(ad.getDevicegroup());
                gbjf.setDeviceaddr(addr);
                gbjf.setPointaddr(i);
                // 获取数据库中使用的设备传感器
                Gbjfsensor record = gbjfsensorServiceImpl.getModel(gbjf);
                if (record == null) {
                    setText("当前数据库无监测点：设备地址" + addr + "的监测点" + i + " ！ 请先添加该监测点！");
                    continue;
                }
                if (record.getInuse() == 1) {
                    // 数据解析起始位置 6为地址+功能码+数据长度 20为传感器id+传感器类型 60为一个传感器数据信息的总长度
                    int start_index = 6 + ((i - 1) * 64);
                    String sensorname = str.substring(start_index, start_index += 16);
                    gbjf.setSensorname(sensorname);
                    // 电池电量
                    String electricity_str = str.substring(start_index += 4, start_index += 4);
                    // 幅值
                    String amplitude_str = str.substring(start_index, start_index += 4);
                    // 如果传感器获得的值为FFFF则跳过该传感器
                    if ("FFFF".equals(electricity_str) || "FFFF".equals(amplitude_str)) {
                        continue;
                    }
                    AddAndUpdate(record,gbjf, Integer.parseInt(electricity_str, 16), parseHex4(amplitude_str));
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            setText("从设备返回的数据有误！请检查串口！");
        }
    }

        @Transactional
        private void AddAndUpdate(Gbjfsensor record,Gbjfsensor gbjf,int electricity,int amplitude) {
            /*int alarmLevel = 0;// 报警等级
            String alarmMessage = "";// 报警消息*/
            //打印获得的传感器数据
            setText(record.getPointname()+": 传感器id:"+ record.getSensorname()+ " 电池电量: " + electricity + " % "+
                    " 局放幅值"+amplitude+" dBm"
                    );
            //报警逻辑
            //判断是否设置了报警值
            if (record.getElectricityalarmrelievevalue() == null || record.getElectricityalarmvalue() == null || record.getElectricitywarnvalue() == null
                    || record.getElectricitywarnrelievevalue() == null||
            record.getAmplitudealarmrelievevalue() == null || record.getAmplitudealarmvalue() == null || record.getAmplitudewarnvalue() == null
                    || record.getAmplitudewarnrelievevalue() == null
            ) {
                setText("设备地址" + record.getDeviceaddr()+ "的监测点" + record.getPointaddr() + " 未设置报警值！");
                return;
            }
            //设置电量
            gbjf.setLastelectricity(electricity*1f);
            //设置电量报警等级
            gbjf.setLastelectricityalarmstatus(GetAlarmStatus(isnull(gbjf.getLastelectricity()), isnull(record.getElectricityalarmvalue()),
                    isnull(record.getElectricityalarmrelievevalue()), isnull(record.getElectricitywarnvalue()), isnull(record.getElectricitywarnrelievevalue()),
                    isnull(record.getLastelectricityalarmstatus()), false,"电池剩余电量", record.getDevicegroup(),record.getDeviceaddr(),record.getPointname(),record.getPointaddr()));
            //设置幅值
            gbjf.setLastamplitude(amplitude*1f);
            //设置幅值报警等级
            gbjf.setLastamplitudealarmstatus(GetAlarmStatus(isnull(gbjf.getLastamplitude()), isnull(record.getAmplitudealarmvalue()),
                    isnull(record.getAmplitudealarmrelievevalue()), isnull(record.getAmplitudewarnvalue()), isnull(record.getAmplitudewarnrelievevalue()),
                    isnull(record.getLastamplitudealarmstatus()), true,"局放幅值", record.getDevicegroup(),record.getDeviceaddr(),record.getPointname(),record.getPointaddr()));
            //设置总报警等级
            gbjf.setLastalarmlevel(Math.max(gbjf.getLastelectricityalarmstatus(),gbjf.getLastamplitudealarmstatus()));
            gbjf.setLastalarmmessage(GetAlarmMessage(gbjf.getLastelectricityalarmstatus(),"电池剩余电量")+
                    GetAlarmMessage(gbjf.getLastamplitudealarmstatus(),"局放幅值"));
            gbjf.setLastcommunicationstatus(0);
            gbjf.setLastdatatime(new Date());
            gbjf.setLasthisdatatime(addHistory(record));
            if ( gbjfsensorServiceImpl.Update(gbjf, false) == 0) {
                setText("更新实时数据失败，请检查数据库连接");
            }
        }

    private Date addHistory(Gbjfsensor sensor) {
        if (sensor != null) {
            if (sensor.getLasthisdatatime() == null) {
                add(sensor);
                return new Date();
            } else {
                long lasttime = 0;
                long nowtime = 0;
                try {
                    lasttime = todate(sensor.getLasthisdatatime()).getTime();
                    nowtime = todate(new Date()).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                int timersp = 60000;
                if (sensor.getLastalarmlevel() != 0) {
                    timersp = ad.getHisalarmtimersp() * 1000;
                } else {
                    timersp = ad.getHistimersp() * 1000;
                }
                if (lasttime + timersp < nowtime) {
                    add(sensor);
                    return new Date();
                }
            }
        }
        return null;
    }

    private void add(Gbjfsensor sensor) {
        Gbjfhistory his = new Gbjfhistory();
        his.setDeviceaddr(sensor.getDeviceaddr());
        his.setDevicegroup(sensor.getDevicegroup());
        his.setAlarmlevel(sensor.getLastalarmlevel());
        his.setAlarmmessage(sensor.getLastalarmmessage());
        his.setDatatime(sensor.getLastdatatime());
        his.setPointname(sensor.getPointname());
        his.setPointaddr(sensor.getPointaddr());
        his.setStationid(sensor.getStationid());
        his.setAmplitude(sensor.getLastamplitude());
        his.setElectricity(sensor.getLastelectricity());
        his.setAmplitudealarmstatus(sensor.getLastamplitudealarmstatus());
        his.setElectricityalarmstatus(sensor.getLastelectricityalarmstatus());
        his.setAddrname(sensor.getAddrname());
        his.setSensorname(sensor.getSensorname());
        gbjfsensorServiceImpl.Add(his);
    }

    @Async("threadPool")
    public void startSendThread(Appdevice Appdevice) throws Exception {
        checkType = "crc16";
        issend.put(Thread.currentThread().getId(), true);
        String cstr = "";
        String cmdtype = "";
        String nametype = "";
        int timersp = (int) Math.round(Appdevice.getTimersp() * 1000);
        while (issend.get(Thread.currentThread().getId()) != null) {
            if (isrun) {
                if (addrindex > Appdevice.getAddrmax() || addrindex < Appdevice.getAddrmin())
                    addrindex = Appdevice.getAddrmin();
                cstr = String.format(Appdevice.getCmd(), String.format("%02X", addrindex));
                cstr = cstr + CRC16.calcCrc16(cstr);
                Send(cstr);
                reSend[addrindex]++;
                if (reSend[addrindex] > 3) {
                    gbjfsensorServiceImpl.UpdateStatus(ad, addrindex, 1);
                    reSend[addrindex] = 0;
                    addrindex++;
                }
            } else if (rescode != 0) {
                setText(resmsg[rescode]);
            }
            Thread.sleep(timersp);
        }
    }
}
